package com.mall.malladminbackend.service;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.mall.malladminbackend.dto.InsertMenuDto;
import com.mall.malladminbackend.dto.MenusDto;
import com.mall.malladminbackend.entity.Menu;
import com.mall.malladminbackend.mapper.MenuMapper;
import com.mall.malladminbackend.mapper.MenuParentMapper;
import com.mall.malladminbackend.model.MenuModel;
import com.mall.malladminbackend.model.R;
import lombok.AllArgsConstructor;
import org.apache.commons.beanutils.PropertyUtils;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import java.util.*;
import java.util.stream.Collectors;

@Service
@AllArgsConstructor
public class MenuService {

    private MenuMapper menuMapper;
    private MenuParentMapper menuParentMapper;

    public R getMenuModels(String name) {
        List<Menu> menus = menuMapper.getMenuOfUser(name);

        if(!CollectionUtils.isEmpty(menus)) {
            List<Menu> btns = new ArrayList<>();

            // 根据parentId对 MenuModel进行分组
            Map<Integer, List<MenuModel>> menuModels = menus.stream()
                    .filter(m -> {
                        Integer type = m.getType();
                        if(type == 2) {
                            btns.add(m);
                        }
                        return type < 2;
                    })
                    .map(this::transferMenuToMenuModel)  // 将Menu转换为MenuModel
                    .collect(Collectors.groupingBy(MenuModel::getParentId));   // 根据ParentId进行分组

            // 拿到顶级菜单
            List<MenuModel> root = menuModels.get(0);  // 1
            // 根据orderNum
            root.sort(Comparator.comparingInt(MenuModel::getOrderNum));

            Map<Integer, List<String>> menu2Perms = classifyPerms(btns);

            generateMenuTree(root, menuModels, menu2Perms);
            return R.buildSuccess(root);
        }else {
            return R.buildFailure("没有任何权限");
        }
    }

    /**
     * 将按钮权限进行归类，Map的 key 当前菜单的id，Map的Value是权限
     */
    public Map<Integer, List<String>> classifyPerms(List<Menu> btns) {
        Map<Integer, List<String>> result = new HashMap<>();
        /**
        Map<Integer, List<Menu>> menuToBtn = btns.stream().collect(Collectors.groupingBy(Menu::getParentId));
        menuToBtn.forEach((k, v) -> result.put(k, v.stream().map(m -> m.getPerms()).collect(Collectors.toList())));
         */
        /**
        btns.stream().collect(Collectors.groupingBy(Menu::getParentId))
                .forEach((k, v) -> result.put(k, v.stream().map(m -> m.getPerms()).collect(Collectors.toList())));
         */
        Map<Integer, List<Menu>> menuToBtn = btns.stream().collect(Collectors.groupingBy(Menu::getParentId));

        // v的类型是 List<Menu>
        menuToBtn.forEach((k, v) -> {
            List<String> ps = v.stream().map(m -> m.getPerm()).collect(Collectors.toList());
            result.put(k, ps);
        });
        return result;
    }

    // 生成菜单的递归树
    public void generateMenuTree(List<MenuModel> menuModelList, Map<Integer,
            List<MenuModel>> menuModels, Map<Integer, List<String>> menu2Perms) {
        if(!CollectionUtils.isEmpty(menuModelList)) {
            menuModelList.forEach(m -> {
                Integer id = m.getId();
                // 获取它所有的儿子
                List<MenuModel> children = menuModels.get(id);

                if(!CollectionUtils.isEmpty(children)) {
                    children.sort(Comparator.comparingInt(MenuModel::getOrderNum));
                    m.setChildren(children);
                    generateMenuTree(children, menuModels, menu2Perms);
                }else {   // 如果某个菜单没有子菜单，那么说明该菜单已经到最低端，就是到页面了
                    List<String> perms = menu2Perms.get(id);  // 拿到对应的菜单
                    if(!CollectionUtils.isEmpty(perms)) {
                        m.getMeta().setPerms(perms);
                    }
                }
            });
        }
    }

    // 将Menu转换为 MenuModel
    public MenuModel transferMenuToMenuModel(Menu menu) {
        MenuModel mm = new MenuModel();
        try {
            // 属性相同才拷贝
            PropertyUtils.copyProperties(mm, menu);
            mm.setPath(menu.getUrl());

            if(menu.getParentId().equals(0)) {  // 顶级菜单
                mm.setComponent("Layout");
            }else {
                mm.setComponent(menu.getName());
            }

            MenuModel.Meta meta = new MenuModel.Meta();
            PropertyUtils.copyProperties(meta, menu);
            mm.setMeta(meta);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return mm;
    }

    //菜单递归
    public R getMenuTree(){
        return R.buildSuccess(menuMapper.getMenuTree(0));
    }

    //递归删除
    public R deleteMenus(Integer oneId){
        //把要删除的id放到集合中
        ArrayList ids = new ArrayList<Integer>();
        ids.add(oneId);
        //调用递归方法
        this.getIds(ids,oneId);
        //批量删除
        menuMapper.deleteBatchIds(ids);
        return R.buildSuccess();
    }
    //递归删除方法
    public void getIds(ArrayList<Integer> ids, Integer parentId){
        //查询下一级级菜单
        QueryWrapper<Menu> qw = new QueryWrapper<>();
        List<Menu> menuList = menuMapper.selectList(qw.eq("parent_id",parentId));
        //循环遍历，获取下一级的菜单id，并添加到要删除的id集合中
        for (Menu menu : menuList) {
            Integer id = menu.getId();
            ids.add(id);
            //递归调用
            this.getIds(ids,id);
        }
    }
    //查询菜单数据
    public R selectMenus(Integer id){
        return R.buildSuccess(menuMapper.getAllMenus(id));
    }
    //修改菜单

    public R updateMenus(MenusDto menusDto) throws Exception {
        Menu menu = new Menu();
        PropertyUtils.copyProperties(menu,menusDto);
        menuMapper.updateById(menu);
        return R.buildSuccess();
    }

    //递归查询菜单上面的父菜单名称（无用）
    public R queryAllParentName(Integer id) {
        return R.buildSuccess(menuParentMapper.getAllMenuParent(id));
    }
    //查询父菜单名
    public R getParentName(Integer type) {
        return R.buildSuccess(menuMapper.selectParentName(type));
    }
    //添加菜单
    public R insertMenus(InsertMenuDto insertMenuDto) throws Exception {
        Menu menu = new Menu();
        PropertyUtils.copyProperties(menu,insertMenuDto);
        menuMapper.insertMenus(insertMenuDto);
        return R.buildSuccess();
    }
}
